package top.huacc.codeing;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.print.PageFormat;
import java.awt.print.Paper;
import java.awt.print.Printable;
import java.awt.print.PrinterException;
import java.awt.print.PrinterJob;

/**
 * 高级图片打印类
 * <p>
 * 该类实现了Printable接口，提供了将BufferedImage打印到打印机的功能。
 * 支持设置打印份数和图片适应页面的选项。
 * <p>
 * 使用示例:
 * BufferedImage image = ImageIO.read(new File("example.jpg"));
 * AdvancedImagePrinter printer = new AdvancedImagePrinter(image);
 * printer.setCopies(2); // 设置打印2份
 * printer.setFitToPage(true); // 设置图片适应页面大小
 * printer.print(); // 显示打印对话框并打印
 */
public class AdvancedImagePrinter implements Printable {
    private BufferedImage image;     // 要打印的图片
    private int copies = 1;          // 打印份数，默认为1份
    private boolean fitToPage = true; // 是否适应页面大小，默认为true
    private boolean noBorder = false; // 是否无边框打印
    private boolean vertical = false; // 是否竖向打印（6英寸照片）
    private double paperWidth = -1;   // 相纸宽度（英寸）
    private double paperHeight = -1;  // 相纸高度（英寸）
    private int dpi = 300;            // 打印分辨率（DPI）

    /**
     * 构造函数
     *
     * @param image 要打印的BufferedImage对象
     */
    public AdvancedImagePrinter(BufferedImage image) {
        this.image = image;
    }

    /**
     * 设置打印份数
     *
     * @param copies 打印份数
     */
    public void setCopies(int copies) {
        this.copies = copies;
    }

    /**
     * 设置是否将图片适应页面大小
     *
     * @param fitToPage true:图片适应页面大小; false:按图片原始大小打印
     */
    public void setFitToPage(boolean fitToPage) {
        this.fitToPage = fitToPage;
    }

    /**
     * 设置相纸尺寸
     *
     * @param width  相纸宽度（英寸）
     * @param height 相纸高度（英寸）
     * @param dpi    打印分辨率（DPI）
     */
    public void setPaperSize(double width, double height, int dpi) {
        this.paperWidth = width;
        this.paperHeight = height;
        this.dpi = dpi;
    }

    /**
     * 实现Printable接口的print方法
     *
     * @param graphics   打印图形上下文
     * @param pageFormat 页面格式
     * @param pageIndex  页码索引
     * @return PAGE_EXISTS表示有内容打印，NO_SUCH_PAGE表示无内容打印
     * @throws PrinterException 打印异常
     */
    @Override
    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
        // 如果页码超过打印份数，返回无页面标识
        if (pageIndex >= copies) {
            return NO_SUCH_PAGE;
        }

        Graphics2D g2d = (Graphics2D) graphics.create();

        // 根据设置决定如何打印
        if (paperWidth > 0 && paperHeight > 0) {
            // 如果设置了相纸尺寸，则按照相纸尺寸打印
            printWithPaperSize(g2d, pageFormat);
        } else if (noBorder && vertical) {
            // 6英寸照片竖向无边框打印
            print6InchVerticalNoBorder(g2d, pageFormat);
        } else if (fitToPage) {
            fitImageToPage(g2d, pageFormat);
        } else {
            drawImageOriginalSize(g2d, pageFormat);
        }

        g2d.dispose();
        return PAGE_EXISTS;
    }

    /**
     * 根据相纸尺寸进行打印
     *
     * @param g2d        Graphics2D对象
     * @param pageFormat 页面格式
     */
    private void printWithPaperSize(Graphics2D g2d, PageFormat pageFormat) {
        if (noBorder) {
            // 无边框打印：使用整个纸张尺寸，忽略可打印区域限制
            double paperWidthPoints = paperWidth * 72;
            double paperHeightPoints = paperHeight * 72;

            // 计算缩放比例以填满整个纸张
            double scaleX = paperWidthPoints / image.getWidth();
            double scaleY = paperHeightPoints / image.getHeight();
            double scale = Math.max(scaleX, scaleY); // 确保图片完全覆盖纸张

            // 计算缩放后的图片尺寸
            double scaledWidth = image.getWidth() * scale;
            double scaledHeight = image.getHeight() * scale;

            // 计算居中位置，确保图片覆盖整个纸张
            double x = (paperWidthPoints - scaledWidth) / 2;
            double y = (paperHeightPoints - scaledHeight) / 2;

            // 设置裁剪区域为整个纸张，实现真正的无边框效果
            g2d.setClip(0, 0, (int) paperWidthPoints, (int) paperHeightPoints);
            
            // 设置高质量渲染
            g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

            // 无边框打印：按计算的缩放比例和居中位置绘制图片，确保完全覆盖纸张
            // 使用Math.max确保图片至少覆盖整个纸张，多余部分会被裁剪
            g2d.drawImage(image, (int) x, (int) y, (int) scaledWidth, (int) scaledHeight, null);
        } else {
            // 有边框打印：使用可打印区域
            double pageWidth = pageFormat.getImageableWidth();
            double pageHeight = pageFormat.getImageableHeight();

            // 计算缩放比例以适应可打印区域
            double scaleX = pageWidth / image.getWidth();
            double scaleY = pageHeight / image.getHeight();
            double scale = Math.min(scaleX, scaleY); // 确保图片完整显示在可打印区域内

            // 计算缩放后的图片尺寸
            double scaledWidth = image.getWidth() * scale;
            double scaledHeight = image.getHeight() * scale;

            // 计算居中显示的坐标位置（相对于可打印区域）
            double x = pageFormat.getImageableX() + (pageWidth - scaledWidth) / 2;
            double y = pageFormat.getImageableY() + (pageHeight - scaledHeight) / 2;

            // 按计算的尺寸和位置绘制图片
            g2d.drawImage(image, (int) x, (int) y, (int) scaledWidth, (int) scaledHeight, null);
        }
    }

    /**
     * 将图片适应页面大小进行绘制
     *
     * @param g2d        Graphics2D对象
     * @param pageFormat 页面格式
     */
    private void fitImageToPage(Graphics2D g2d, PageFormat pageFormat) {
        double pageWidth = pageFormat.getImageableWidth();   // 页面可打印宽度
        double pageHeight = pageFormat.getImageableHeight(); // 页面可打印高度

        // 计算宽度和高度的缩放比例
        double scaleX = pageWidth / image.getWidth();
        double scaleY = pageHeight / image.getHeight();
        // 取较小的缩放比例以确保图片完整显示在页面内
        double scale = Math.min(scaleX, scaleY);

        // 计算居中显示的坐标位置
        double x = (pageWidth - image.getWidth() * scale) / 2;
        double y = (pageHeight - image.getHeight() * scale) / 2;

        // 按计算的尺寸和位置绘制图片
        g2d.drawImage(image, (int) x, (int) y,
                (int) (image.getWidth() * scale),
                (int) (image.getHeight() * scale), null);
    }

    /**
     * 按图片原始大小进行绘制
     *
     * @param g2d        Graphics2D对象
     * @param pageFormat 页面格式
     */
    private void drawImageOriginalSize(Graphics2D g2d, PageFormat pageFormat) {
        double pageWidth = pageFormat.getImageableWidth();   // 页面可打印宽度
        double pageHeight = pageFormat.getImageableHeight(); // 页面可打印高度

        // 计算居中显示的坐标位置
        double x = (pageWidth - image.getWidth()) / 2;
        double y = (pageHeight - image.getHeight()) / 2;

        // 按原始尺寸绘制图片
        g2d.drawImage(image, (int) x, (int) y, null);
    }

    /**
     * 启动打印任务
     * 会显示系统打印对话框，用户可选择打印机和设置打印参数
     *
     * @throws PrinterException 打印异常
     */
    public void print() throws PrinterException {
        PrinterJob printJob = PrinterJob.getPrinterJob(); // 获取打印任务对象
        printJob.setPrintable(this);                      // 设置打印内容
        // 设置打印份数
        printJob.setCopies(copies);

        // 如果设置了相纸尺寸，则修改页面格式以使用整个页面
        if (paperWidth > 0 && paperHeight > 0) {
            PageFormat pageFormat = printJob.defaultPage();
            // 设置页面尺寸为整个相纸尺寸（转换为点）
            double paperWidthPoints = paperWidth * 72;   // 转换为点 (1英寸 = 72点)
            double paperHeightPoints = paperHeight * 72;
            Paper paper = new Paper();
            paper.setSize(paperWidthPoints, paperHeightPoints);
            // 设置可打印区域为整个纸张，实现真正的无边框
            paper.setImageableArea(0, 0, paperWidthPoints, paperHeightPoints);
            pageFormat.setPaper(paper);
            printJob.setPrintable(this, pageFormat);
        }
        // 直接打印，无需用户确认
        printJob.print();
    }

    /**
     * 6英寸照片竖向无边框打印
     *
     * @param g2d        Graphics2D对象
     * @param pageFormat 页面格式
     */
    private void print6InchVerticalNoBorder(Graphics2D g2d, PageFormat pageFormat) {
        // 6英寸照片的标准尺寸，转换为点（72点=1英寸）
        double targetWidthPoints = (vertical ? 4 : 6) * 72;   // 竖向4英寸宽，横向6英寸宽
        double targetHeightPoints = (vertical ? 6 : 4) * 72;  // 竖向6英寸高，横向4英寸高

        // 计算缩放比例以填满整个目标区域
        double scaleX = targetWidthPoints / image.getWidth();
        double scaleY = targetHeightPoints / image.getHeight();
        double scale = Math.max(scaleX, scaleY); // 确保图片完全覆盖目标区域

        // 计算缩放后的图片尺寸
        double scaledWidth = image.getWidth() * scale;
        double scaledHeight = image.getHeight() * scale;

        // 计算居中位置，确保图片覆盖整个目标区域
        double x = (targetWidthPoints - scaledWidth) / 2;
        double y = (targetHeightPoints - scaledHeight) / 2;

        // 设置裁剪区域为整个6英寸照片区域
        g2d.setClip(0, 0, (int) targetWidthPoints, (int) targetHeightPoints);
        
        // 设置高质量渲染
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);

        // 无边框打印：按计算的缩放比例和居中位置绘制图片，确保完全覆盖目标区域
        // 使用Math.max确保图片至少覆盖整个目标区域，多余部分会被裁剪
        g2d.drawImage(image, (int) x, (int) y, (int) scaledWidth, (int) scaledHeight, null);
    }

    /**
     * 将图片旋转90度（用于竖向打印）
     *
     * @param image 原始图片
     * @return 旋转后的图片
     */
    private BufferedImage rotateImage90(BufferedImage image) {
        int width = image.getWidth();
        int height = image.getHeight();
        BufferedImage rotatedImage = new BufferedImage(height, width, image.getType());
        Graphics2D g2d = rotatedImage.createGraphics();
        g2d.translate((rotatedImage.getWidth() - width) / 2, (rotatedImage.getHeight() - height) / 2);
        g2d.rotate(Math.toRadians(90), width / 2.0, height / 2.0);
        g2d.drawImage(image, 0, 0, null);
        g2d.dispose();
        return rotatedImage;
    }

    /**
     * 设置是否无边框打印
     *
     * @param noBorder true:无边框打印; false:正常打印
     */
    public void setNoBorder(boolean noBorder) {
        this.noBorder = noBorder;
    }

    /**
     * 设置是否竖向打印（6英寸照片专用）
     *
     * @param vertical true:竖向打印; false:横向打印
     */
    public void setVertical(boolean vertical) {
        this.vertical = vertical;
    }

    /**
     * 获取打印份数
     *
     * @return 打印份数
     */
    public int getCopies() {
        return copies;
    }

    /**
     * 获取相纸宽度
     *
     * @return 相纸宽度（英寸）
     */
    public double getPaperWidth() {
        return paperWidth;
    }

    /**
     * 获取相纸高度
     *
     * @return 相纸高度（英寸）
     */
    public double getPaperHeight() {
        return paperHeight;
    }

    /**
     * 设置为6寸照片无边框打印模式
     * 
     * @param vertical true:竖向打印(4x6英寸); false:横向打印(6x4英寸)
     */
    public void set6InchPhoto(boolean vertical) {
        this.vertical = vertical;
        this.noBorder = true;
        this.fitToPage = false;
        if (vertical) {
            // 竖向：4英寸宽 x 6英寸高
            setPaperSize(4.0, 6.0, 300);
        } else {
            // 横向：6英寸宽 x 4英寸高
            setPaperSize(6.0, 4.0, 300);
        }
    }
    
    /**
     * 调试方法：打印当前设置信息
     */
    public void printDebugInfo() {
        System.out.println("=== AdvancedImagePrinter Debug Info ===");
        System.out.println("Paper Size: " + paperWidth + " x " + paperHeight + " inches");
        System.out.println("No Border: " + noBorder);
        System.out.println("Vertical: " + vertical);
        System.out.println("Fit To Page: " + fitToPage);
        System.out.println("Image Size: " + (image != null ? image.getWidth() + " x " + image.getHeight() : "null"));
        System.out.println("DPI: " + dpi);
        System.out.println("Copies: " + copies);
        System.out.println("===========================================");
    }

}